/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.task.zkex;

import cn.easyplatform.lang.Mirror;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.type.Constants;
import cn.easyplatform.web.annotation.Builder;
import cn.easyplatform.web.ext.ComponentBuilder;
import cn.easyplatform.web.ext.EntityExt;
import cn.easyplatform.web.ext.Writable;
import cn.easyplatform.web.ext.ZkExt;
import cn.easyplatform.web.ext.calendar.Calendars;
import cn.easyplatform.web.ext.jm.Mind;
import cn.easyplatform.web.ext.ocez.OrgChart;
import cn.easyplatform.web.ext.zul.*;
import cn.easyplatform.web.task.OperableHandler;
import cn.easyplatform.web.task.api.DefaultDataHandler;
import cn.easyplatform.web.task.zkex.list.boost.HierarchyBoostBuilder;
import cn.easyplatform.web.task.zkex.list.boost.ReportBoostBuilder;
import cn.easyplatform.web.task.zkex.list.grid.ActionboxGridBuilder;
import cn.easyplatform.web.task.zkex.list.grid.CatalogGridBuilder;
import cn.easyplatform.web.task.zkex.list.grid.DetailGridBuilder;
import cn.easyplatform.web.task.zkex.list.grid.LoaderGridBuilder;
import cn.easyplatform.web.task.zkex.list.tree.ActionboxTreeBuilder;
import cn.easyplatform.web.task.zkex.list.tree.CatalogTreeBuilder;
import cn.easyplatform.web.task.zkex.list.tree.DetailTreeBuilder;
import cn.easyplatform.web.task.zkex.list.tree.LoaderTreeBuilder;
import cn.easyplatform.web.task.zkex.simple.*;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public final class ComponentBuilderFactory {

    private ComponentBuilderFactory() {
    }

    public final static ComponentBuilder getEntityBuilder(OperableHandler main,
                                                          EntityExt comp) {
        return getEntityBuilder(main, comp, null, null);
    }

    public final static ComponentBuilder getEntityBuilder(OperableHandler main,
                                                          EntityExt comp, Component anchor) {
        return getEntityBuilder(main, comp, null, anchor);
    }

    public final static ComponentBuilder getEntityBuilder(OperableHandler main,
                                                          EntityExt comp, Component ref, Component anchor) {
        if (comp instanceof Datalist) {
            Datalist dl = (Datalist) comp;
            if (Constants.REPORT.equals(dl.getType()))
                return new ReportBoostBuilder(main, dl, anchor);
            if (Constants.HIERARCHY.equalsIgnoreCase(dl.getType()))
                return new HierarchyBoostBuilder(main, dl, anchor);
            if (!Strings.isBlank(dl.getGroup())
                    || !Strings.isBlank(dl.getLevelBy())) {// 有分组或者有层级定义
                if (dl.getType().equalsIgnoreCase(Constants.CATALOG))
                    return new CatalogTreeBuilder(main, dl, anchor);
                if (dl.getType().equalsIgnoreCase(Constants.DETAIL))
                    return new DetailTreeBuilder(main, dl, anchor);
                if (dl.getType().equalsIgnoreCase(Constants.ACTIONBOX))
                    return new ActionboxTreeBuilder(main, (Datalist) comp,
                            (Actionbox) ref, anchor);
                if (dl.getType().equalsIgnoreCase(Constants.LOADER))
                    return new LoaderTreeBuilder(main, (Datalist) comp,
                            (Loader) ref, anchor);
                return new CatalogTreeBuilder(main, dl, anchor);
            } else {
                if (dl.getType().equalsIgnoreCase(Constants.CATALOG))
                    return new CatalogGridBuilder(main, dl, anchor);
                if (dl.getType().equalsIgnoreCase(Constants.DETAIL))
                    return new DetailGridBuilder(main, dl, anchor);
                if (dl.getType().equalsIgnoreCase(Constants.ACTIONBOX))
                    return new ActionboxGridBuilder(main, (Datalist) comp,
                            (Actionbox) ref, anchor);
                if (dl.getType().equalsIgnoreCase(Constants.LOADER))
                    return new LoaderGridBuilder(main, (Datalist) comp,
                            (Loader) ref, anchor);
                return new CatalogGridBuilder(main, dl, anchor);
            }
        } else if (comp instanceof JReport)
            return new JReportBuilder(main, (JReport) comp);
        else if (comp instanceof Taskbox)
            return new TaskboxBuilder(main, (Taskbox) comp);
        else {
            Builder builder = comp.getClass().getAnnotation(Builder.class);
            if (builder != null) {
                Mirror<ComponentBuilder> mirror = (Mirror<ComponentBuilder>) Mirror
                        .me(builder.value());
                return mirror.born(main, comp, ref, anchor);
            }
        }
        throw new WrongValueException((Component) comp,
                Labels.getLabel("component.builder.not.found",
                        new Object[]{"<"
                                + comp.getClass().getSimpleName().toLowerCase()
                                + ">"}));
    }

    public final static ComponentBuilder getZkBuilder(OperableHandler main,
                                                      ZkExt comp) {
        if (comp instanceof ComboboxExt)
            return new ComboboxBuilder(main, (ComboboxExt) comp);
        if (comp instanceof RadiogroupExt)
            return new RadiogroupBuilder(main, (RadiogroupExt) comp);
        if (comp instanceof Actionbox)
            return new ActionboxBuilder(main, (Actionbox) comp);
        if (comp instanceof ChosenboxExt)
            return new ChosenboxBuilder(main, (ChosenboxExt) comp);
        if (comp instanceof Import)
            return new ImportBuilder(main, (Import) comp);
        if (comp instanceof Checkgroup)
            return new CheckgroupBuilder(main, (Checkgroup) comp);
        if (comp instanceof Loader)
            return new LoaderBuilder(main, (Loader) comp);
        if (comp instanceof SelectboxExt)
            return new SelectboxBuilder(main, (SelectboxExt) comp);
        if (comp instanceof Explorer)
            return new ExplorerBuilder(main, (Explorer) comp);
        if (comp instanceof Movebox)
            return new MoveboxBuilder(main, (Movebox) comp);
        if (comp instanceof ListboxExt)
            return new ListboxBuilder(main, (ListboxExt) comp);
        if (comp instanceof GridExt)
            return new GridBuilder(main, (GridExt) comp);
        if (comp instanceof Buttongroup)
            return new ButtongroupBuilder(main, (Buttongroup) comp);
        if (comp instanceof Wandbox)
            return new WandboxBuilder(main, (Wandbox) comp);
        if (comp instanceof Timeslots)
            return new TimeslotsBuilder(main, (Timeslots) comp);
        if (comp instanceof BandboxExt)
            return new BandboxBuilder(main, (BandboxExt) comp);
        if (comp instanceof TreeExt)
            return new TreeBuilder(main, (TreeExt) comp);
        if (comp instanceof Writable)
            return new CommonFileBuilder(main, (Component) comp);
        if (comp instanceof Surveybox)
            return new SurveyboxBuilder(main, (Surveybox) comp);
        if (comp instanceof FisheyebarExt)
            return new FisheyebarBuilder(main, (FisheyebarExt) comp);
        if (comp instanceof StepbarExt)
            return new StepbarBuilder(main, (StepbarExt) comp);
        if (comp instanceof LinelayoutExt)
            return new LinelayoutBuilder(main, (LinelayoutExt) comp);

        String name = comp.getClass().getSimpleName();
        if (name.equals("Mind"))
            return new MindBuilder(main, (Mind) comp);
        if (name.equals("Bpmdesigner"))
            return new BpmdesignerBuilder(main, comp);
        if (name.equals("Calendars"))
            return new CalendarsBuilder(main, (Calendars) comp);
        if (name.equals("PivottableExt"))
            return new PivottableBuilder(main, comp);
//        if (name.equals("FxGrid"))
//            return new FxGridBuilder(main, comp);
//        if (name.equals("FxCard"))
//            return new FxCardBuilder(main, comp);
//        if (name.equals("FxCardEx"))
//            return new FxCardExBuilder(main, comp);
        if (name.equals("Kalendars"))
            return new KalendarsBuilder(main, (Kalendars) comp);
        if (name.equals("OrgChart"))
            return new OrgChartBuilder(main, (OrgChart) comp);
        Builder builder = comp.getClass().getAnnotation(Builder.class);
        if (builder != null) {
            Mirror<?> me = Mirror
                    .me(builder.value());
            return (ComponentBuilder) me.born(new DefaultDataHandler(main), comp);
        } else
            throw new WrongValueException((Component) comp,
                    Labels.getLabel("component.builder.not.found",
                            new Object[]{"<"
                                    + comp.getClass().getSimpleName().toLowerCase()
                                    + ">"}));
    }

    public final static ComponentBuilder getZkBuilder(ListSupport support,
                                                      ZkExt comp, Component anchor) {
        if (comp instanceof ComboboxExt)
            return new ComboboxBuilder(support, (ComboboxExt) comp, anchor);
        if (comp instanceof RadiogroupExt)
            return new RadiogroupBuilder(support, (RadiogroupExt) comp, anchor);
        if (comp instanceof Actionbox)
            return new ActionboxBuilder(support, (Actionbox) comp, anchor);
        if (comp instanceof ChosenboxExt)
            return new ChosenboxBuilder(support, (ChosenboxExt) comp, anchor);
        if (comp instanceof Import)
            return new ImportBuilder(support, (Import) comp, anchor);
        if (comp instanceof Checkgroup)
            return new CheckgroupBuilder(support, (Checkgroup) comp, anchor);
        if (comp instanceof Loader)
            return new LoaderBuilder(support.getMainHandler(), (Loader) comp);
        if (comp instanceof SelectboxExt)
            return new SelectboxBuilder(support, (SelectboxExt) comp, anchor);
        if (comp instanceof Explorer)
            return new ExplorerBuilder(support.getMainHandler(), (Explorer) comp);
        if (comp instanceof Wandbox)
            return new WandboxBuilder(support, (Wandbox) comp, anchor);
        if (comp instanceof Buttongroup)
            return new ButtongroupBuilder(support, (Buttongroup) comp, anchor);
        if (comp instanceof BandboxExt)
            return new BandboxBuilder(support, (BandboxExt) comp, anchor);
        if (comp instanceof ListboxExt)
            return new ListboxBuilder(support, (ListboxExt) comp, anchor);
        if (comp instanceof GridExt)
            return new GridBuilder(support, (GridExt) comp, anchor);
        if (comp instanceof TreeExt)
            return new TreeBuilder(support, (TreeExt) comp, anchor);
        if (comp instanceof StepbarExt)
            return new StepbarBuilder(support, (StepbarExt) comp, anchor);
        if (comp instanceof LinelayoutExt)
            return new LinelayoutBuilder(support, (LinelayoutExt) comp, anchor);

        if (comp instanceof Writable)
            return new CommonFileBuilder(support, (Component) comp);
        String name = comp.getClass().getSimpleName();
        if (name.equals("Mind"))
            return new MindBuilder(support, (Mind) comp, anchor);
        if (name.equals("Bpmdesigner"))
            return new BpmdesignerBuilder(support.getMainHandler(), comp);
        Builder builder = comp.getClass().getAnnotation(Builder.class);
        if (builder != null) {
            Mirror<?> me = Mirror
                    .me(builder.value());
            return (ComponentBuilder) me.born(new DefaultDataHandler(support, anchor), comp);
        } else
            throw new WrongValueException((Component) comp,
                    Labels.getLabel("component.builder.not.found",
                            new Object[]{"<"
                                    + comp.getClass().getSimpleName().toLowerCase()
                                    + ">"}));
    }
}
